import 'dart:async';

import 'package:flutter/cupertino.dart';

import '../effects/base/base_effect.dart';
import '../effects/effect_template.dart';
import '../painter/frame_animation_painter.dart';

class FixedAnimationContainer extends StatefulWidget {
  final BaseEffect animationEffect;
  final EffectOperation? operation;

  const FixedAnimationContainer(this.animationEffect,
      {Key? key, this.operation})
      : super(key: key);

  @override
  State<StatefulWidget> createState() => _FixedAnimationContainerState();
}

class _FixedAnimationContainerState extends State<FixedAnimationContainer>
    with SingleTickerProviderStateMixin {
  int currentFrame = 0;
  Timer? timer;
  List<List<List<Color>>>? frames;

  @override
  void didUpdateWidget(covariant FixedAnimationContainer oldWidget) {
    if(oldWidget.operation != widget.operation){
      timer?.cancel();
      currentFrame = 0;
      getFrames().then((frameData) {
        frames = frameData;
        startTimerFrames();
      });
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void initState() {
    getFrames().then((frameData) {
      frames = frameData;
      startTimerFrames();
    });

    super.initState();
  }

  Future<List<List<List<Color>>>> getFrames() async {
    List<List<List<Color>>> animationFrames = await widget.animationEffect.getFrames(operation: widget.operation);
    return animationFrames;
  }

  void startTimerFrames() {
    if (frames?.isNotEmpty ?? false) {
      if (frames!.length > 1) {
        int frameDuration;
        var baseEffect = widget.animationEffect;
        if (baseEffect is EditableAnimationEffect) {
          if (baseEffect.enableSpeed) {
            int speed =
                widget.operation?.speed ?? baseEffect.speedRange.defaultValue;
            frameDuration = (baseEffect.speedRange.end - speed + 1) *
                widget.animationEffect.frameDuration;
          } else {
            frameDuration = widget.animationEffect.frameDuration;
          }
        } else {
          int? speed = widget.operation?.speed;
          if (speed != null) {
            frameDuration = (10 - speed) * widget.animationEffect.frameDuration;
          } else {
            frameDuration = widget.animationEffect.frameDuration;
          }
        }

        timer = Timer.periodic(Duration(milliseconds: frameDuration), (timer) {
          setState(() {
            currentFrame++;
            if (currentFrame > frames!.length - 1) {
              currentFrame = 0;
            }
          });
        });
      } else {
        setState(() {
          currentFrame = 0;
        });
      }
    }
  }

  @override
  void dispose() {
    timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return frames != null
        ? CustomPaint(
            painter: FrameAnimationPainter(frames![currentFrame]),
            child: Container(),
          )
        : const SizedBox();
  }
}
